; void colorizar_asm (
; unsigned char *src,
; unsigned char *dst,
; int m,
; int n,
; int src_row_size,
; int dst_row_size,
; float alpha
; );

; Parámetros:
; rdi = src
; rsi = dst
; rdx = m
; rcx = n
; r8 = src_row_size
; r9 = dst_row_size
; xmm0 = alpha

global colorizar_asm

section .data

    align 16
    mascaraFinal: db 7, 8, 9, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255
    RRRGGGBBB: db 0, 3, 6, 255, 1, 4, 7, 255, 2, 5, 8, 255, 255, 255, 255, 255
    RGB: db 0, 255, 255, 255, 4, 255, 255, 255, 8, 255, 255, 255, 255, 255, 255, 255
    PXLCHN: db 0, 255, 255, 255, 1, 255, 255, 255, 2, 255, 255, 255, 255, 255, 255, 255
    CHNPXL: db 0, 4, 8, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
    DOSCINCOCINCO: dd 255.0, 255.0, 255.0, 0
    UNO: dd 1.0

section .text

colorizar_asm:

    	push rbp
    	mov rbp, rsp
    	push rbx
	push r12
	push r13
	push r14
	push r15

	mov r10d, 1				; contador para columnas
	mov r11d, 1 				; contador de filas
    	mov r12d, edx 				; guardo m
    	mov r13d, ecx 				; guardo n

; calculo los resultados de chi

	movss xmm4, [UNO] 			; xmm4 = 0|0|0|1.0
	addss xmm4, xmm0 			; xmm4 = 0|0|0|1.0 + alfa 
	movss xmm5, [UNO] 			; xmm5 = 0|0|0|1.0
	subss xmm5, xmm0 			; xmm5 = 0|0|0|1.0 - alfa 

; copio la mascara de 255

	movdqu xmm6, [DOSCINCOCINCO] 		; xmm6 = 0|255.0|255.0|255.0


cicloFilas:

    	mov r10d, 3 				; r10d = x = 3

cicloColumnas:

;voy a calcular la posicion de la primer fila para procesar el pixel

	mov eax, r8d 				; copio el row_size de src
	mov ebx, r11d 				; copio la fila actual
	dec ebx 				; retroceso uno para calcular la primer fila
	mul ebx 				; multiplico
	add eax, r10d 				; avanzo la cantidad de columnas
	sub eax, 3 				; ajusto por el RGB
	mov r15, rax				; aca tengo la posicion desde donde leer las filas

; calculo donde va a escribir el resultado

	xor rax, rax
	mov eax, r9d 				; copio el row_size de dst
	mov ebx, r11d 				; copio la fila actual
	mul ebx 				; multiplico
	add eax, r10d 				; avanzo a la columna actual
	mov r14d, eax				; guardo la posicion donde voy a escribir en dst
    	xor rcx, rcx 				; pongo en 0 rcx por si necesito correr por la ultima fila

;chequeo si llegue a la ultima fila
	lea ebx, [r12d -2]			; copio m a una variable para no modificarlo
    	cmp r11d, ebx
    	jl calcularCoordenadas 			; no estoy en la ultima fila

;llegue a la ultima fila

;    	mov eax, r13d 				; copio n para multiplicar
;    	mov ebx, 3 				
;    	mul ebx 				
;    	sub eax, r10d 				; resto las columnas
;    	cmp eax, 13
;    	jge calcularCoordenadas 		; si no es necesario completar salto
;    	mov ecx, 7 				; por si tengo que completar los que faltan

calcularCoordenadas:

;copio las 3 filas con las que se va a trabajar
    	sub r15d, ecx 				; a la posicion donde estoy le resto un offset dependiendo en que fila estoy
	movdqu xmm1, [rdi + r15] 		; copio los de la fila n-1
	add r15d, r8d				; sumo un row_size para adelantar una fila
	movdqu xmm2, [rdi + r15] 		; copio los de la fila n
	add r15d, r8d				; sumo un row_size para adelantar una fila
	movdqu xmm3, [rdi + r15] 		; copio los de la fila n+1

; calculo el pixel a modificar
	add r15d, 3				; avanzo 3
	sub r15d,r8d				; resto un row_size para volver a la fila n
	movdqu xmm7, [rdi + r15] 		; copio el pixel a modificar
    	pshufb xmm7, [PXLCHN] 			; le aplico una mascara para obtener xmm7: 0|R|G|B
    	cvtdq2ps xmm7, xmm7 			; convierto de pixel a float 

    	cmp ecx, 0				;chequeo en que fila estoy
    	je acomodar 
; estoy en la ultima tengo que corregir las posiciones
    	pshufb xmm1, [mascaraFinal]		; xmm1: 000R|GBRG|BRGB
    	pshufb xmm2, [mascaraFinal]		; xmm2: 000R|GBRG|BRGB
    	pshufb xmm3, [mascaraFinal]		; xmm3: 000R|GBRG|BRGB

acomodar:

    	pshufb xmm1, [RRRGGGBBB]		; xmm1: 0|0RRR|0GGG|0BBB
   	pshufb xmm2, [RRRGGGBBB]		; xmm2: 0|0RRR|0GGG|0BBB
    	pshufb xmm3, [RRRGGGBBB]		; xmm3: 0|0RRR|0GGG|0BBB
    	pmaxub xmm1, xmm2			; guardo en xmm1 los maximos entre mxx1 y xmm2
    	pmaxub xmm1, xmm3			; guardo en xmm1 los maximos entre mxx1 y xmm2

	movdqu xmm13, xmm1			; xmm13: 0|0RRR|0GGG|0BBB
	movdqu xmm15, xmm1 			; xmm15: 0|0RRR|0GGG|0BBB
    	psrld xmm1, 8 				; xmm1: 0|00RR|00GG|00BB
    	movdqu xmm14, xmm1 			; xmm14: 0|00RR|00GG|00BB

    	psrld xmm13, 8 				; xmm13: 0|00RR|00GG|00BB
    	psrld xmm13, 8 				; xmm13: 0|000R|000G|000B
   	pshufb xmm15, [RGB] 			; xmm15: 0|000R|000G|000B
    	pshufb xmm14, [RGB] 			; xmm14: 0|000R|000G|000B

    	pmaxub xmm13, xmm15			; calculo los maximos definitivos
   	pmaxub xmm13, xmm14 			; me da los maximo definitivos xmm13: 0|maxR|maxG|maxB

;copio los maximos a registros
    	movd edx, xmm13 			; copio el max B
    	pshufd xmm15, xmm13, 1 			; dejo en la parte mas baja el max G
    	movd eax, xmm15 			; copio el max G
    	pshufd xmm15, xmm13, 2 			; dejo en la parte mas baja el max R
    	movd ecx, xmm15 			; copio el max R

;calculo chi
    	cmp ecx, eax				; veo quien es mayor o R o G
    	jl restoAlfaR 				; me dio que R >= G
    	cmp ecx, edx				; veo quien es mayor o R o B
    	jl restoAlfaR 				; me dio que R >= B
	movdqu xmm8,xmm4			; xmm8 = 0|0|0|1.0 + alfa
    	jmp calculoG

restoAlfaR:
	movdqu xmm8,xmm5			; xmm8 = 0|0|0|1.0 - alfa

calculoG:
    	cmp ecx, eax				; veo quien es mayor G o R
    	jge restoAlfaG 				; me dio R < G
    	cmp eax, edx				; veo quien es mayor G o B
    	jl restoAlfaG 				; me dio G >= B
	movdqu xmm9, xmm4			; xmm9 = 0|0|0|1.0 + alfa
    	jmp calculoB

restoAlfaG:
	movdqu xmm9, xmm5			; xmm9 = 0|0|0|1.0 - alfa

calculoB:
    	cmp ecx, edx				; veo quien es mayor o R o B
    	jge restoAlfaB 				; me dio R < B
    	cmp eax, edx				; veo quien es mayor o G o B
    	jge restoAlfaB	 			; me dio G < B
	movdqu xmm10,xmm4			; xmm10 = 0|0|0|1.0 + alfa
    	jmp finChi

restoAlfaB:
	movdqu xmm10,xmm5			; xmm10 = 0|0|0|1.0 - alfa

finChi:
    	pshufd xmm8, xmm8, 0xC6 		; xmm8 = 0000 chiR 0000 0000
    	pshufd xmm9, xmm9, 0xE1 		; xmm9 = 0000 0000 chiG 0000
    	addps xmm8, xmm9 			; xmm8 = 0000 chiR chiG 0000
    	addps xmm8, xmm10 			; xmm8 = 0000 chiR chiG chiB

; traigo de nuevo el pixel actual
    	mulps xmm7, xmm8 			; xmm7: 0|chiR * R|chiG * G|chiB *B
	minps xmm7, xmm6 			; xmm7: 0|R|G|B
	cvtps2dq xmm7, xmm7 			; los convierto de nuevo xmm7: 0|000R|000G|000B
	pshufb xmm7, [CHNPXL] 			; xmm7: 0000|0000|0000|0RGB
	movd eax, xmm7 				; copio en un registro el resultado final
	mov [rsi + r14], eax 			; escribo en dst el resultado final

    	add r10d, 3 				
    	mov eax, r13d 				 
    	mov ebx, 3 				 
    	mul ebx 				 
    	sub eax, 3 				
    	cmp r10d, eax				; veo si ya recorri n
    	jl cicloColumnas 			

    	inc r11d 				
    	mov eax, r12d 				
    	sub eax, 1 				
    	cmp r11d, eax				; veo si ya recorri m
    	jl cicloFilas 

	pop r15
	pop r14
    	pop r13
   	pop r12
    	pop rbx
    	pop rbp
    	ret
